3D 游戏开发
3D 游戏开发
3D 项目设置
# 项目设置 -> Rendering -> Lighting and Shadows
# Directional Light Shadows: PCF16 (for better shadows)
# 项目设置 -> Rendering -> Environment
# Default Clear Color
3D 节点层次
WorldEnvironment
├── DirectionalLight3D
├── Camera3D
├── Player
│ ├── MeshInstance3D
│ ├── CollisionShape3D
│ └── ...
└── Level
├── StaticBody3D
│ ├── MeshInstance3D
│ └── CollisionShape3D
└── ...
角色移动
3D 角色移动
extends CharacterBody3D
@export var speed: float = 5.0
@export var sprint_multiplier: float = 1.5
func _physics_process(delta: float) -> void:
var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction != Vector3.ZERO:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
else:
velocity.x = move_toward(velocity.x, 0, speed)
velocity.z = move_toward(velocity.z, 0, speed)
move_and_slide()
3D 相机跟随
extends Camera3D
@export var target: Node3D
@export var offset: Vector3 = Vector3(0, 5, 10)
@export var smooth_speed: float = 10.0
func _process(delta: float) -> void:
if target:
var target_pos = target.global_position + offset
global_position = lerp(global_position, target_pos, smooth_speed * delta)
look_at(target.global_position)
3D 物理
RigidBody3D
extends RigidBody3D
@export var force: float = 100.0
func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
if Input.is_action_pressed("ui_up"):
apply_central_force(Vector3.FORWARD * force)
StaticBody3D
用于静态物体,不会移动但有碰撞。
Area3D
用于检测区域,无碰撞但可以检测。
extends Area3D
signal player_entered
func _on_body_entered(body: Node3D) -> void:
if body.is_in_group("player"):
player_entered.emit()
3D 渲染
MeshInstance3D
# 更改网格
mesh = preload("res://models/player.glb")
# 更改材质
set_surface_override_material(0, preload("res://materials/player_material.tres"))
创建简单形状
extends MeshInstance3D
func _ready() -> void:
# 立方体
mesh = BoxMesh.new()
# 球体
mesh = SphereMesh.new()
# 圆柱体
mesh = CylinderMesh.new()
光照
DirectionalLight3D (方向光)
模拟太阳光,平行光线。
@export_range(0, 1) var shadow_intensity: float = 0.5
func _ready() -> void:
shadow_enabled = true
light_energy = 1.0
OmniLight3D (点光源)
向四面八方发光。
extends OmniLight3D
func _ready() -> void:
omni_range = 20.0
omni_attenuation = 2.0
SpotLight3D (聚光灯)
锥形光照。
extends SpotLight3D
func _ready() -> void:
spot_range = 30.0
spot_angle = 45.0
环境
WorldEnvironment
extends WorldEnvironment
func _ready() -> void:
environment.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
environment.ambient_light_color = Color(0.5, 0.5, 0.5)
Sky
# 使用程序化天空
var sky = Sky.new()
var sky_material = ProceduralSkyMaterial.new()
sky.sky_material = sky_material
environment.sky = sky
3D 动画
AnimationTree
extends AnimationTree
func _process(delta: float) -> void:
var input_vector = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
parameters["move_speed"] = input_vector.length()
地形
GridMap
extends GridMap
func _ready() -> void:
# 设置网格大小
cell_size = Vector3(2, 2, 2)
# 放置单元格
set_cell_item(Vector3i(0, 0, 0), 0, 0)
3D 射线检测
extends Node3D
@onready var camera = $Camera3D
func _input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.pressed:
var ray_origin = camera.project_ray_origin(event.position)
var ray_direction = camera.project_ray_normal(event.position)
var ray_param = PhysicsRayQueryParameters3D.create(ray_origin, ray_origin + ray_direction * 1000)
var result = get_world_3d().direct_space_state.intersect_ray(ray_param)
if result:
print("Hit: ", result.collider.name)
3D 坐标系统
- 原点 (0, 0, 0) 在场景中心
- X 轴向右为正
- Y 轴向上为正
- Z 轴向前为负,向后为正
性能优化建议
- 合并静态网格
- 使用 LOD (Level of Detail)
- 减少动态光源
- 使用遮挡剔除
- 优化碰撞形状